#ifndef __GLF_REMOTE_CONTROLLER_H_INCLUDED__
#define __GLF_REMOTE_CONTROLLER_H_INCLUDED__

#include <glf/config.h>

#include <glf/core/bytearray.h>
#include <glf/core/event.h>
#include <glf/core/types.h>
#include <glf/net/socket.h>

#include <string>

namespace glf
{

	struct CoreEvent;

	namespace remote
	{
		class Canvas;
		class Renderer;

		//MessageHeader
		struct MessageHeader //4 bytes
		{
		public:
			MessageHeader() {}
			MessageHeader(uchar messageType) 
			{
				mMagic[0] = 'R';
				mMagic[1] = 'M';
				mMessageType = messageType;
				mMessageSize = HeaderSize(); 
			}

		public:
			uchar *Data() { return reinterpret_cast<uchar *>(this); }
			uchar GetMessageType() const { return mMessageType; }		
			static size_t HeaderSize() { return sizeof(MessageHeader); }
			size_t MessageSize() const { return mMessageSize; }
			bool IsMagic() const { return mMagic[0] == 'R' && mMagic[1] == 'M'; }		
			void UpdateMessageSize(size_t messageSize)
			{ 
				GLF_ASSERT(messageSize < (uchar)-1);
				mMessageSize = (uchar)messageSize;
			}

		private:
			uchar mMagic[2];
			uchar mMessageType;
			uchar mMessageSize;		
		};

		//Controller
		class Controller : public EventReceiver
		{
		public:
			Controller(
				// addrIP values:
				//  - for a server: ip = 0 and server port
				//  - for a client: server IP and server port
				AddrIp4 addrIP);
			virtual ~Controller();

		public:		
			void Draw(Renderer *renderer);
			bool OnEvent(const CoreEvent &evt);
			void Update();

		private:
			bool Connect();		
			void DrawEvent(const CoreEvent &evt);
			bool IsConnected();
			void ReceiveEvent(EventDataReader &reader);
			void ReceiveIdentification(EventDataReader &reader);		
			void ReceiveMessages();
			void SendMessage(const uchar *data, int size);
			void SendEvent(const CoreEvent &evt);
			void SendIdentification();		
			void SendQuit();		

		private:
			Canvas *mCanvas;
			AddrIp4 mAddrIP;
			bool mIsServer;
			std::string mHostname;
			Socket mSocket;
			int64 mNetRetryTimeMS;
			bool mShowRemoteEvent;
			bool mShowLocalEvent;
			bool mIsUpdatedWithoutDraw;
		};

	} //eon remote
} //eon glf


#endif //__GLF_REMOTE_CONTROLLER_H_INCLUDED__